#include "xmpp.h"
#include "client.h"
#include <string.h>




/* fonctions balises ouvrantes */
void (*elements[27])(void *data, const char *name, const char **atts) = {
  &XmppMuet,   &XmppAuth,   &XmppMuet, /* @ A B */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* C D E */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* F G H */
  &XmppIqStanza,   &XmppMuet,   &XmppMuet, /* I J K */
  &XmppMuet,   &XmppMessage,   &XmppMuet, /* L M N */
  &XmppMuet,   &XmppMuet,   &XmppQuery, /* O P Q */
  &XmppRegister,   &XmppStream, &XmppMuet, /* R S T */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* U V W */
  &XmppMuet,   &XmppMuet,   &XmppMuet  /* X Y Z */
};


/* fonctions balises fermantes */
void (*endElements[27])(void *data, const char *name) = {
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* @ A B */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* C D E */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* F G H */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* I J K */
  &XmppMuet,   &XmppCloseMessage,   &XmppMuet, /* L M N */
  &XmppMuet,   &XmppMuet,   &XmppCloseQuery, /* O P Q */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* R S T */
  &XmppMuet,   &XmppMuet,   &XmppMuet, /* U V W */
  &XmppMuet,   &XmppMuet,   &XmppMuet  /* X Y Z */
};




/* cherche un attribut d'une balise */
char * find_attribute(const char *name, const char **atts)
{
  int j;
  char *p;
	
  for (j = 0; atts[j]; j+=2)
    {
      if (!strcasecmp(atts[j], name))
	{
	  p = (char *) malloc(strlen(atts[j+1]));
	  strcpy(p, atts[j+1]);
	  return p;
	}
    }
  return NULL;
}


void XmppMuet(){
  fprintf(stdout, "Muet\n");
  return ;
}


/* actions en début de balise */
void XMLCALL
startElement(void *data, const char *name, const char **atts)
{ 
  fprintf(stdout, "balise %s\n", name);
  
  struct xmppClient * own = (struct xmppClient *) data;
  
  own->lastTag = (char *)malloc((strlen(name) + 1) * sizeof(char));
  
  /* strcpy(own->lastTag, name); /* positionner lastBalise */
  
  elements[hash_balise(name)](data, name, atts);
  
}


/* actions en fin de balise */
void XMLCALL
endElement(void *data, const char *name)
{
  fprintf(stdout, "sortie balise %s\n", name);
  endElements[hash_balise(name)](data, name);
}


/* actions à la rencontre d'un texte */
void HandlerCharacterData(void *data, const char *text, int len){
  
  struct xmppClient * own = (struct xmppClient *) data;  
  
  if(own->message_att && !strncmp(own->lastTag, text, len) ){ /* afficher un message reçu */

    char msg[1000];strncpy(msg, text, len); msg[len] = '\0';
    fprintf(stdout, msg);
  }
  
  
}


/* traitement lors de l'ouverture d'un stream */
void XMLCALL
XmppStream(void *data, const char *name, const char **atts){

  struct xmppClient * own = (struct xmppClient *) data;
  
  /* ouvertre du flux coté serveur*/
  if(!strncmp(name,"stream:stream", strlen("strem:stream"))){
    /* on verra ce qu'on pourra faire */
  }
  if(!strncmp(name,"stream:features", strlen("strem:features"))){
    /* on verra ce qu'on pourra faire */
  }
}


/* traitement du stanza iq */
void XMLCALL
XmppIqStanza(void *data, const char *name, const char **atts){
  

  if(!strncmp(name, "iq", 2)){ // = <iq ...
    
    /* On fera ptet un truc ici pour les atributs, controle ...  */
  }
}


/* traitement de la balise <query sous la balise <iq */
void XMLCALL
XmppQuery(void *data, const char *name, const char **atts){
  
  struct xmppClient * own = (struct xmppClient *) data;
  
  if(!strncmp(name, "query", 5)){ //<query ...
    /* trouver l'opération */
    char * xmlns = find_attribute("xmlns", atts);
    
    /* tester si c'est l'enregistrement */
    if(!strcmp(xmlns, "jabber:iq:register")){
      
      /* envoie du login et du password */
      char question[REP_MAX_SIZE];
      sprintf(question, "<iq type='set' id='reg2'><query xmlns='jabber:iq:register'><username>%s</username><password>%s</password></query></iq>", own->username, own->password);
      if(write(own->desc, question, strlen(question))==-1){
	perror("write");
	exit(EXIT_SUCCESS);
      }
      
    }
    
    /* on suppose que xmlns='jabber:iq:OPERATION' */
    
  }
}





/* traitement lors de l'ouverture d'un stream reception du namespace de <register> */
void XMLCALL
XmppRegister(void *data, const char *name, const char **atts){

  struct xmppClient * own = (struct xmppClient *) data;


}


/* traitement lors de l'ouverture d'un stream : reception du namespace de <auth> */
void XMLCALL
XmppAuth(void *data, const char *name, const char **atts){

  struct xmppClient * own = (struct xmppClient *) data;
  
  /* on sauvegarde le namespace de l'enregistrement */
  if(!strncmp(name,"auth", strlen("auth"))){
    /* on verra ce qu'on pourra faire */
    own->auth_ns = find_attribute("xmlns" ,atts);

    fprintf(stdout, "bien reçu le register ns : %s\n", own->auth_ns);
  }

}







/* a la rencontre d'une balise fermante query */
void XMLCALL
XmppCloseQuery(void *data, const char *name){

  
  if(!strncmp(name, "query", 5)){ //</query>
    
    /* tester si operation = enregistrement && demande : type='set' */
    
  }
  
}


/*********************************************************************


/* à la rencontre de la balise message  */
void XMLCALL
XmppMessage(void *data, const char *name, const char ** atts){
  
  struct xmppClient * own = (struct xmppClient *) data;  
  // TODO il faut aussi verficier qu'on est bien dans l'état de reception de message
  if(!strncmp(name, "message", 8)){ //<message>   


    own->state = CHAT;    
    own->message_att = 1;
    own -> chat_dest = find_attribute("from", atts);

  }
}



/* à la rencontre de la balise de fin d'un message </message */
void XMLCALL
XmppCloseMessage(void *data, const char *name){
  
  struct xmppClient * own = (struct xmppClient *) data;  
   // TODO il faut aussi verficier qu'on est bien dans l'état d'envoi de messages
  if(!strncmp(name, "message", 8)){ //<message>   
        own->message_att = 0;
  }
  
}


/* à la rencontre de la balise de début de corps d'un message <body */
void XMLCALL
XmppBody(void *data, const char *name){
  
  struct xmppClient * own = (struct xmppClient *) data;  
  
  if(!strncmp(name, "body", 8) && own->message_att){ //<message> 
  }
  
}





/*******************************************************************/
